package com.webserver.http;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HttpServletResponse {
    private Socket socket;
    private int statusCode = 200;
    private String statusReason= "OK";
    private File contentFile;
    private byte[] contentData;//以一组字节作为正文发送

    private ByteArrayOutputStream baos;

    private Map<String,String> headers = new HashMap<>();

    public HttpServletResponse(Socket socket){
        this.socket = socket;
    }

    public void response() throws IOException {

        sendBefore();
        //1.状态行
        sendStatusLine();
        //2.响应头
        sendHeaders();
        //3.响应正文
        sendContent();
    }

    private void sendBefore(){
        if(baos != null){//如果baos不为null，则说明用过这个流写出过动态数据
            contentData = baos.toByteArray();//将内部的字节数组获取(动态数据)
            addHeader("Content-Length",contentData.length+"");
        }
    }

    private void sendStatusLine() throws IOException {
        println("HTTP/1.1"+" "+statusCode+" "+statusReason);
        System.out.println("发送响应");
        System.out.println("HTTP/1.1"+" "+statusCode+" "+statusReason);
    }
    private void sendHeaders() throws IOException {

        Set<Map.Entry<String,String>> entries = headers.entrySet();
        for (Map.Entry<String,String> h : entries){
            println(h.getKey() + ": " + h.getValue());
            System.out.println(h.getKey()+": " + h.getValue());
        }
        println("");
    }
    private void sendContent() throws IOException {
        if(contentData != null){//是否有动态数据作为正文
            OutputStream os = socket.getOutputStream();
            os.write(contentData);
//            System.out.println("响应正文"+new String(contentData,"UTF-8"));
        }else if(contentFile != null){
            try(
                    FileInputStream fis = new FileInputStream(contentFile);
            ){
                OutputStream out = socket.getOutputStream();
                byte[] data = new byte[1024*10];
                int len;
                while ((len = fis.read(data)) != -1){
                    out.write(data,0,len);
//                    System.out.println("响应正文"+new String(data,"UTF-8"));
                }
            }
        }




    }



    private void println(String line) throws IOException {
        OutputStream out = socket.getOutputStream();
        byte[] data = line.getBytes(StandardCharsets.ISO_8859_1);

        out.write(data);
        out.write(13);
        out.write(10);
    }

    public void sendRedirect(String uri){
        statusCode = 302;
        statusReason = "Moved Temporarily";
        addHeader("Location",uri);//该方法中设置状态代码为302，并在响应头中包含Location指定需要浏览器重新发起请求的路径
        //将原来Controller中内部跳转页面的操作全部改为重定向。在消息头添加Location: uri,浏览器
    }

    public int getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }

    public String getStatusReason() {
        return statusReason;
    }

    public void setStatusReason(String statusReason) {
        this.statusReason = statusReason;
    }

    public File getContentFile() {
        return contentFile;
    }

    public void setContentFile(File contentFile) {
        this.contentFile = contentFile;

        if(contentFile !=null){
            try {
                String type = Files.probeContentType(contentFile.toPath());
                if(type != null){
                    addHeader("Content-Type",type);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            addHeader("Content-Length",contentFile.length()+"");
        }

    }

    public void addHeader(String key,String value){
        headers.put(key,value);
    }

    private ByteArrayOutputStream getOutputStream(){
        if(baos == null){//baos没有new过，才进行new
            baos = new ByteArrayOutputStream();
        }

        return baos;
    }

    public PrintWriter getWriter(){
        OutputStream os = getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(os,StandardCharsets.UTF_8);
        BufferedWriter bw = new BufferedWriter(osw);
        return new PrintWriter(bw,true);
    }

    public void setContentType(String type){
        addHeader("Content-Type",type);
    }

}
